<script setup lang="ts">
import type { ComponentInstance } from 'vue'
import { nextTick, ref, toRaw } from 'vue'

import { CircleHelp } from 'lucide-vue-next'
import type { BaseNode, FlowDirection, SubprocessNode } from '@/types'
import type DingDesigner from '@/components/ding-designer/DingDesigner.vue'
import TippyPopover from '@/components/ding-flow/base/TippyPopover.vue'
import { createPresetProcess } from '@/utils/element-utils'
import JsonData from '@/mock/json-data.json'
import { parseJsonToNodeTree, transformToJson } from '@/data-transform/json-transform'
import { transformToXML } from '@/data-transform/bpmn-transform'

const dir = ref<FlowDirection>('vertical')
const dingFlowDesignerRef = ref<ComponentInstance<typeof DingDesigner>>()

const processData = ref(createPresetProcess())

// 切换方向
function toggleDir() {
  dingFlowDesignerRef.value?.toggleDirection()
}
// 切换主题
function toggleTheme() {
  const isDark = document.body.getAttribute('arco-theme') === 'dark'
  if (isDark) {
    document.body.removeAttribute('arco-theme')
  }
  else {
    document.body.setAttribute('arco-theme', 'dark')
  }
}

const zoomValue = ref(1)
function changeZoomValue(value: number) {
  zoomValue.value = value
}

function logNodeData(node?: BaseNode) {
  console.log('click', node)
}

function toggleRoot(node?: BaseNode) {
  console.log('dblclick', node)
  dingFlowDesignerRef.value?.toggleRoot(node as SubprocessNode)
}

function center() {
  dingFlowDesignerRef.value?.fitViewport()
}

const modalVisible = ref<boolean>(false)
const modalMode = ref<string>('xml')
const codeString = ref<string>('')

function getData() {
  console.log(toRaw(processData.value))
  codeString.value = JSON.stringify(transformToJson(toRaw(processData.value)), null, 2)
  modalMode.value = 'json'
  modalVisible.value = true
}
function setData() {
  const mockData = parseJsonToNodeTree(JsonData)
  processData.value = mockData!
  nextTick(() => center())
}

async function generateXML() {
  const { xml } = await transformToXML(processData.value)
  codeString.value = xml
  modalMode.value = 'xml'
  modalVisible.value = true
}
</script>

<template>
  <div class="demo-page">
    <a-space class="demo-btns">
      <a-button type="primary" @click="toggleDir">
        切换排列
      </a-button>
      <a-button type="primary" @click="toggleTheme">
        切换主题
      </a-button>
      <a-button type="primary" @click="center">
        自适应居中
      </a-button>
      <a-input-number size="small" :model-value="zoomValue" read-only />
      <a-button type="primary" @click="toggleRoot()">
        还原根节点
      </a-button>
      <a-button type="primary" @click="setData()">
        导入数据
      </a-button>
      <a-button type="primary" @click="getData()">
        预览 json
      </a-button>
      <a-button type="primary" @click="generateXML()">
        预览 xml
      </a-button>

      <a-button type="primary" class="header-tips">
        <template #icon>
          <CircleHelp :size="12" />
        </template>
        Tips
      </a-button>
    </a-space>
    <TippyPopover target=".demo-page .header-tips">
      <template #default>
        <p>支持垂直、水平两种布局方式</p>
        <p>支持亮色、暗色两种主题</p>
        <p>支持画布的自由拖拽和缩放</p>
        <p>支持节点拖拽调整位置</p>
        <p>可自动适应容器大小，调整显示比例</p>
        <p>支持子流程嵌套与子流程独立显示</p>
        <p>支持按需求扩展 BPMN 节点解析</p>
        <p>统一的元素操作方法管理与操作验证（或操作前置验证）方法管理</p>
        <p>支持自定义方法控制元素新增菜单内容</p>
      </template>
    </TippyPopover>

    <a-modal v-model:visible="modalVisible" :footer="false" draggable title="预览" width="64vw">
      <div class="preview-model" style="max-height: 80vh">
        <highlightjs :language="modalMode" :code="codeString" />
      </div>
    </a-modal>

    <DingDesigner
      ref="dingFlowDesignerRef"
      v-model:data="processData"
      :direction="dir"
      @zoom-changed="changeZoomValue"
      @node-click="logNodeData"
      @node-dblclick="toggleRoot"
    />
  </div>
</template>

<style lang="scss">
html,
body,
#app,
.demo-page {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  position: relative;
}
.demo-page {
  display: flex;
  flex-direction: column;
}
.demo-btns {
  display: flex;
  grid-column-start: 1;
  grid-column-end: 3;
  gap: 10px;
  z-index: 10;
  width: 100%;
  .header-tips {
    margin-left: auto;
  }
}
</style>
